﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using com.opttek.optquest;
namespace ConsoleApplication1
{
    class Results
    {
        private KCOptQuest myopt;
        private static Results myinstance;
        private COptQuestSolution solution;
        private string path;
       
        private string SRankName = "//SEQUENCE_RANK.csv";
        private string MResName = "//MACHINE_RESULTS.csv";
        private string CostResName = "//COST_RESULTS.csv";

        public static Results getResultsInstance()
        {
            if (myinstance == null)
                myinstance = new Results();
            return myinstance;
        }

        public void setOpt(KCOptQuest o)
        {
            myopt = o;
            solution = myopt.GetBestSolution();
        }
        public void generateResults(String path)
        {
            this.path = path;
            if (myopt == null)
                return;
            genSequenceRank();
            genMachineResults();
            genCostResults();
            
        }

        private  void genSequenceRank()
        {
            int rank = 0;
            int i = 0;
            double val_ant = 0;
            List<String> values = new List<string>();
            
            try
            {
                using (StreamWriter writer = new StreamWriter(path+SRankName))
                {
                    foreach(String machkey in myopt.mysimdata.mymachines.Keys)
                    {
                        foreach (DesignVariable var in myopt.mycube.getVarsForMachine(machkey))
                        {
                                
                            double value = solution.GetVariableValue(var);
                            i = var.time;
                            if (i>0)
                                val_ant= solution.GetVariableValue(myopt.mycube.machineDesignInternal[machkey][i-1]);
                                
                                if (value != -1 && value != val_ant)
                                {
                                    rank += 1;
                                    values.Add(machkey);
                                    values.Add(var.getMatkey(Convert.ToInt32(value)));
                                    values.Add(rank.ToString());
                                    writer.WriteLine(csvValues(values));
                                    values.Clear();
                                }
                            
                        }
                        
                        rank = 0;
                    }
  
                }
                                
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        
        private void genMachineResults()
        {
            bool producing = false;
            int i;
            int lot = 0;
            int start = 0;
            double val_ant=0;

            List<String> values = new List<string>();
            try
            {
                using (StreamWriter writer = new StreamWriter(path + MResName))
                {
                    foreach (String machkey in myopt.mysimdata.mymachines.Keys)
                    {
                        foreach (DesignVariable var in myopt.mycube.getVarsForMachine(machkey))
                        {
                             double value = solution.GetVariableValue(var);
                             i = var.time;

                             if (i>0)
                                val_ant= solution.GetVariableValue(myopt.mycube.machineDesignInternal[machkey][i-1]);
                                
                                if (value != -1 && !producing)
                                {
                                    producing = true;
                                    start = i;     
                                }

                                if (value != -1 && producing)
                                {
                                    lot += 1;
                                }

                                if (value != val_ant && producing)
                                {
                                    string matkey = var.getMatkey(Convert.ToInt32(value));
                                    String key = machkey + matkey;
                                    MaterialProd matprod = myopt.mysimdata.mymaterialsprod[key];
                                    values.Add(machkey);
                                    values.Add(matkey);
                                    
                                    values.Add((start * myopt.mysimdata.alpha).ToString());
                                    values.Add((lot * matprod.prodrate * myopt.mysimdata.alpha).ToString());
                                    values.Add((lot*myopt.mysimdata.alpha).ToString());
                                    writer.WriteLine(csvValues(values));
                                    values.Clear();
                                    producing = false;
                                    lot = 0;
                                }

                        }
                            if (producing)
                            {
                                DesignVariable var = myopt.mycube.machineDesignInternal[machkey][(int)Math.Floor(myopt.mysimdata.horizon)];
                                double value = solution.GetVariableValue(var);
                                string matkey = var.getMatkey(Convert.ToInt32(value));

                                String key = machkey + matkey;
                                MaterialProd matprod = myopt.mysimdata.mymaterialsprod[key];
                                values.Add(machkey);
                                values.Add(matkey);
                                    
                                values.Add((start * myopt.mysimdata.alpha).ToString());
                                values.Add((lot * matprod.prodrate * myopt.mysimdata.alpha).ToString());
                                values.Add((lot*myopt.mysimdata.alpha).ToString());
                                writer.WriteLine(csvValues(values));
                                values.Clear();
                                producing = false;
                                lot = 0;
                            }
                        }

                        lot = 0;
                        producing = false;
                    }
                


            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private void genCostResults()
        {


            List<String> values = new List<string>();
            try
            {
                using (StreamWriter writer = new StreamWriter(path + CostResName))
                {

                    double revenue = solution.GetObjectiveValue(myopt.revenueuc);
                    values.Add(revenue.ToString());
                    
                    double servlevel = solution.GetVariableValue(myopt.serviceleveluc); ;
                    values.Add(servlevel.ToString());
                    double prodcost = solution.GetVariableValue(myopt.prodcostuc);
                    values.Add(prodcost.ToString());
                    double invcost = solution.GetVariableValue(myopt.holdcostuc);
                    values.Add(invcost.ToString());
                    double bocost = solution.GetVariableValue(myopt.backordercostuc);
                    values.Add(bocost.ToString());
                    double tarinv = solution.GetVariableValue(myopt.tarinvcostuc);
                    values.Add(tarinv.ToString());
                    writer.WriteLine(csvValues(values));
                }


            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private static String csvValues(List<String> values)
        {
            String ans = "";
            foreach (String s in values)
            {
                ans += s;
                ans += ",";
            }
            ans = ans.Remove(ans.Length - 1);
            return ans;
        }
        
    }
}
